package com.yuncheng.spcyApi.utils;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.RateLimiter;
import com.yuncheng.spcyApi.alog.utils.IpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * ip接口限流
 * @author hua
 */
public class IpRateLimiterUtils {

    private static final Logger log = LoggerFactory.getLogger(IpRateLimiterUtils.class);

    /*// 存储IP和对应RateLimiter的映射
    private static final ConcurrentHashMap<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>();

    // 默认的QPS（每秒查询次数）
    private static final double DEFAULT_QPS = 1.0;

    // 获取指定IP的RateLimiter，如果不存在则创建一个
    public static RateLimiter getRateLimiter(String ip) {
        return rateLimiters.computeIfAbsent(ip, key -> RateLimiter.create(DEFAULT_QPS));
    }

    // 尝试执行操作，如果被限流则返回false
    public static boolean tryAcquireOld(String ip) {
        RateLimiter rateLimiter = getRateLimiter(ip);
        return rateLimiter.tryAcquire();
    }*/

    /** 根据key分不同的令牌桶, 每3分钟自动清理缓存 */
    private static Cache<String, RateLimiter> caches = CacheBuilder.newBuilder()
            // 初始化缓存容量大小
//            .initialCapacity()
            //在访问后5分钟清除
            .expireAfterAccess(5, TimeUnit.MINUTES)
            //最大值,超过这个值会清除掉最近没使用到的缓存
            .maximumSize(300)
            .build();

    public static boolean tryAcquire(String key){
        return tryAcquire(key, "key_rate_limit");
    }

    public static boolean tryAcquireIp(){
        return tryAcquire(IpUtils.getIpAddr(), "ip_rate_limit");
    }

    public static boolean tryAcquire(String key, String descName) {
//        double limitPerSec = 2 * 1.0 / 1;
        RateLimiter limiter = null;
        try {
            // 0.5
            limiter = caches.get("rate_limit:"+key, () -> RateLimiter.create(0.5));
            //1秒没获取到
        } catch (ExecutionException e) {
            log.error("获取限流出错: ",e);
        }

        if (limiter != null){
//            boolean b = limiter.tryAcquire(1, TimeUnit.SECONDS);
//            boolean b = limiter.tryAcquire(5, TimeUnit.MINUTES);
            boolean b = limiter.tryAcquire();
            if (!b){
                log.info("限制访问key为 {}，描述为 [{}] 的接口", "rate_limit:"+key, descName);
//                throw new LimitAccessException("接口访问超出频率限制");
                return false;
            }
        }

        return true;
    }

}
